#include "fibevent.h"
#include "wxtl/CompletionPort.h"
#include "wxtl/Fiber.h"

#include "IocpOperation.h"
#include "BaseFiberClientHandler.h"
#include "IocpServerSocketDispatcher.h"
#include "IocpIoBaseInitiator.h"


#include "BaseFiberServer.h"

using wxtl::Fiber;

void IocpServerSocketDispatcher::threadProc()
{
	LDEBUG("Thread{" << GetCurrentThreadId() << "} started");

	Fiber::Init();
	size_t bytes = 0;
	IocpOperation* overlapped = NULL;
	BaseIocpInitiator* initiator = NULL;

	while( !m_server->GetStopEvent().wait(0) )
	{
		bool ret = m_port->WaitStatus(bytes, (ULONG_PTR*)&initiator,(LPOVERLAPPED*)&overlapped,INFINITE);
		

		//in case of terminated completion port
		if(ret == false && overlapped == NULL)
		{
			bytes = 0;
			continue;
		}

		if(overlapped == NULL || initiator == NULL)
		{
			//this should not happen;
			abort();
		}

		//special case for client fiber initialization
		if(!(IocpFiber*)overlapped->m_destination)
		{
			if(overlapped->m_reason != IocpOperation::Init)
			{
				abort();
			}

			BaseFiberClientHandler* client = m_server->CreateClient();
			if(!initiator->Validate())
			{
				abort();
			}
			//init event can be called only with io type of initiator
			client->SetIo((IocpIoBaseInitiator*)initiator);
			overlapped->m_destination = (IocpFiber*) client;
		}

		initiator->OnOperationCompleted(IocpResult(bytes, wxtl::_win32_error(GetLastError()), !ret), overlapped);

		bytes = 0;
		overlapped = NULL;
		initiator = NULL;
	}

	delete this;
}

IocpServerSocketDispatcher::IocpServerSocketDispatcher( CompletionPort* port, BaseFiberServer* server ) :m_port(port)
	,m_server(server)
{
	m_localOps = 0;
	create();
}
